﻿/*--------------------------------------------
 * -------------------------------------------
 * --- CLASS MEDIAN FILTER EXECUTE -----------
 * -------------------------------------------
 * Created By: Roy Scheefhals ----------------
 * 
 * usage: Gebruikt het median filter en zorgt
 * voor de threading en het maken van een Myimage
 * En gebruikt de MedianFilter class voor
 * het uitvoeren van de median
 * (maakt ook nieuwe bitmaps aan)
*/

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace LibraryCS {
    public class MedianExecute : VisionFilter {
        bool gray_channel = false; // true is generate gray channel , false is all RGB channels
        byte[] Graychannel1;
        byte[] Graychannel2;
        byte[] Graychannel3;
        byte[] Graychannel4;

        bool channel1_done = false;
        bool channel2_done = false;
        bool channel3_done = false;
        bool channel4_done = false;

        public MedianExecute(String name)
            : base(name) {
        }

        public override System.Drawing.Bitmap DoAlgorithm(Bitmap sourceImage) {
            //Debug.WriteLine("Inside DoAlgorithm");
            //MyImage sourceim;
            VImage sourceim;
            MedianFilter mf = new MedianFilter(KernelSize);
            Bitmap bmpnew = null;
            if (!gray_channel) {
                sourceim = new VImage(sourceImage);

                Stopwatch tijd = new Stopwatch();
                tijd.Start();

                byte[] Rchannel = mf.DoMedianFilter(sourceim.RedPixels, sourceim);
                byte[] Gchannel = mf.DoMedianFilter(sourceim.GreenPixels, sourceim);
                byte[] Bchannel = mf.DoMedianFilter(sourceim.BluePixels, sourceim);

                tijd.Stop();
                long milsec = tijd.ElapsedMilliseconds;
                //Debug.WriteLine("TIME: " + milsec);

                bmpnew = sourceim.returnNewBitmapOutput(Rchannel, Gchannel, Bchannel);
                //bmpnew.Save("D:\\TESTING.jpg");
                return bmpnew;
            } else {
                Debug.WriteLine("Executing median filter threaded");
                sourceim = new VImage(sourceImage);

                Stopwatch tijd = new Stopwatch();
                tijd.Start();

                // maak jobs aan en laat ze starten
                ThreadStart job1 = delegate { mf.DoMedianFilterThreaded(sourceim.BluePixels, this, sourceim, 0, sourceim.Height / 4, true, 1); };
                ThreadStart job2 = delegate { mf.DoMedianFilterThreaded(sourceim.BluePixels, this, sourceim, sourceim.Height / 4, sourceim.Height / 2, true, 2); };
                ThreadStart job3 = delegate { mf.DoMedianFilterThreaded(sourceim.BluePixels, this, sourceim, sourceim.Height / 2, (sourceim.Height / 2) + (sourceim.Height / 4), true, 3); };
                ThreadStart job4 = delegate { mf.DoMedianFilterThreaded(sourceim.BluePixels, this, sourceim, (sourceim.Height / 2) + (sourceim.Height / 4), sourceim.Height, true, 4); };

                new Thread(job1).Start();
                new Thread(job2).Start();
                new Thread(job3).Start();
                new Thread(job4).Start();

                lock (this) {
                    Monitor.Wait(this);
                }

                tijd.Stop();
                long milsec = tijd.ElapsedMilliseconds;
                Debug.WriteLine("TIME: " + milsec);

                bmpnew = sourceim.returnNewBitmapFromHalfArrays(Graychannel1, Graychannel2, Graychannel3, Graychannel4);
                //bmpnew.Save("D:\\TESTING.jpg");

                Graychannel1 = null;
                Graychannel2 = null;
                Graychannel3 = null;
                Graychannel4 = null;
                channel1_done = false;
                channel2_done = false;
                channel3_done = false;
                channel4_done = false;
                return bmpnew;
            }
        }

        public void setChannel(bool gray) {
            gray_channel = !gray;
        }

        //Notify vanuit de MedianFilter klasse
        public void notifyMeWithChannel(byte[] channel, int id) {
            if (id == 1) {
                //   Debug.WriteLine("CHANNEL " + id + " NOTIFIED BOSS");
                Graychannel1 = channel;
                channel1_done = true;
            }
            if (id == 2) {
                //  Debug.WriteLine("CHANNEL " + id + " NOTIFIED BOSS");
                Graychannel2 = channel;
                channel2_done = true;
            }
            if (id == 3) {
                //  Debug.WriteLine("CHANNEL " + id + " NOTIFIED BOSS");
                Graychannel3 = channel;
                channel3_done = true;
            }
            if (id == 4) {
                //   Debug.WriteLine("CHANNEL " + id + " NOTIFIED BOSS");
                Graychannel4 = channel;
                channel4_done = true;
            }
            if (channel1_done == true && channel2_done == true && channel3_done == true && channel4_done == true) {
                lock (this) {
                    Monitor.Pulse(this);
                }
            }
        }

        #region GUI Functions
        /* 
         * Toegevoegd door: Duncan Jenkins
        */
        public override List<Control> createControls() {
            List<Control> Controls = new List<Control>();

            // Create a Label indictating the type of setting this is
            Label lb = new Label();
            lb.AutoSize = true;
            lb.Text = "Kernel Size";
            lb.Name = "lbKernelSize";

            // Create a TextBox Control for setting the percentage of noise
            TextBox tb = new TextBox();
            tb.Name = "tbKernelSize";
            tb.AcceptsReturn = false;
            tb.MaxLength = 3;
            tb.Multiline = false;
            tb.Size = new Size(50, 25);

            // Add the controls to the list
            Controls.Add(tb);
            Controls.Add(lb);

            // Return the list
            return Controls;
        }

        /* 
         * Toegevoegd door: Duncan Jenkins
        */
        public override void setSettings(List<object> settings) {
            KernelSize = Int32.Parse(((TextBox)settings[0]).Text);
            Debug.WriteLine("Settings entered: " + KernelSize);
        }
        #endregion
    }
}